#pragma once
//============================================================================
// Copyright (C) 2013 Brett R. Jones
//
// Issued to public domain 2013
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================

#include <string>
#include <vector>
#include <VxUtilLib/VxUtilLib.h>
#include <VxUtilLib/DbBase.h>

//! implements settings like ini file using sqlite database
class VxSettings : public DbBase
{
public:
	//=== constants ===//
	static const int	MAX_VALUE_STRING_LEN = 2047;

	//=== vars ===//
	bool				m_bIsValid;

	//=== constructor ===//
	VxSettings();
	//=== destructor ===//
	~VxSettings();

	//=== helpers ===//
	//! return true if is valid
	bool				isValid( void )							{ return m_bIsValid; }
	//! set valid
	void				setIsValid( bool bValid )				{ m_bIsValid = bValid; }

	//=== overrides ===//
	//! override onCreateTables to create our tables
	virtual RCODE		onCreateTables( int iDbVersion );
	//! override onDeleteTables to delete our tables
	virtual RCODE		onDeleteTables( int oldDbVersion );

	//=== methods ===//
	//! startup Settings.. if database doesnt exist then create it and call DbCreateTables
	RCODE				vxSettingsStartup( const char * pDbFileName );
	//! shutdown Settings
	void				vxSettingsShutdown( void );

	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, bool& bValue );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, int& bValue );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, S8& s8Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, U8& u8Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, S16& s16Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, U16& u16Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, S32& s32Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, U32& u32Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, S64& s64Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, U64& u64Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, F32& f32Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, F64& f64Value );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, std::string& strValue );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, const char * pValue );
	//! set and save value to database
	void				setIniValue( const char * pKey, const char * pSettingName, std::vector<std::string>& aoStrValues );
	//! save a object as blob into the database
	void				setIniValue( const char * pKey, const char * pSettingName, void * pvObject, int iObjectLen );

	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, bool& bValue, bool bDefault = false );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, int& iValue, int iDefault = 0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, S8& s8Value, S8 s8Default = 0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, U8& u8Value, U8 u8Default = 0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, S16& s16Value, S16 s16Default = 0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, U16& u16Value, U16 u16Default = 0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, S32& s32Value, S32 s32Default = 0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, U32& u32Value, U32 u32Default = 0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, S64& s64Value, S64 s64Default = 0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, U64& u64Value, U64 u64Default = 0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, F32& f32Value, F32 f32Default = 0.0f );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, F64& f64Value, F64 f64Default = 0.0 );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, std::string& strValue, const char * pDefault = "" );
	//! get value from database.. return default if doesnt exist
	void				getIniValue( const char * pKey, const char * pSettingName, char * pRetBuf, int iBufLen, const char * pDefault = "" );
	//! get value from database
	void				getIniValue( const char * pKey, const char * pSettingName, std::vector<std::string>& aoStrValues );
	//! copy blob from database.. if length doesnt match will return false
	bool				getIniValue( const char * pKey, const char * pSettingName, void * pvRetBuf, int iBufLen );

private:
	//! prepare sql statement set value
	RCODE				prepareIniSet(	sqlite3_stmt ** ppoRetSqlStatement, 
										const char *	pTableName,
										const char *	pKey, 
										const char *	pSettingName ); 

	//! prepare sql statement to query value
	RCODE				prepareIniQuery(	sqlite3_stmt ** ppoRetSqlStatement, 
											const char *	pTableName,
											const char *	pKey, 
											const char *	pSettingName ); 

	//! finalize and close db after setting 
	RCODE				finalizeIniSetTransaction(	sqlite3_stmt * poSqlStatement, bool bErrorOccured = false ); 

	//! finalize and close db
	RCODE				finalizeIniGetTransaction(	sqlite3_stmt * poSqlStatement, bool bErrorOccured = false ); 
};
